home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / tar.gnu / tar-dist / create.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-01-23  |  27.5 KB  |  1,191 lines

  1. /* Create a tar archive.
  2.    Copyright (C) 1988 Free Software Foundation
  3.  
  4. This file is part of GNU Tar.
  5.  
  6. GNU Tar is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 1, or (at your option)
  9. any later version.
  10.  
  11. GNU Tar is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GNU Tar; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. /*
  21.  * Create a tar archive.
  22.  *
  23.  * Written 25 Aug 1985 by John Gilmore, ihnp4!hoptoad!gnu.
  24.  *
  25.  * @(#)create.c 1.36 11/6/87 - gnu
  26.  */
  27. #include <sys/types.h>
  28. #include <sys/stat.h>
  29. #include <sys/file.h>
  30. #include <stdio.h>
  31.  
  32. /* JF: this one is my fault */
  33. /* #include "utils.h" */
  34.  
  35. #ifndef V7
  36. #include <fcntl.h>
  37. #endif
  38.  
  39. #ifndef    MSDOS
  40. #include <pwd.h>
  41. #include <grp.h>
  42. #endif
  43.  
  44. #ifdef BSD42
  45. #include <sys/dir.h>
  46. #else
  47. #ifdef MSDOS
  48. #include <sys/dir.h>
  49. #else
  50. #ifdef USG
  51. #include "dirent.h"
  52. #define direct dirent
  53. #define DP_NAMELEN(x) strlen((x)->d_name)
  54. #else
  55. /*
  56.  * FIXME: On other systems there is no standard place for the header file
  57.  * for the portable directory access routines.  Change the #include line
  58.  * below to bring it in from wherever it is.
  59.  */
  60. #include "ndir.h"
  61. #endif
  62. #endif
  63. #endif
  64.  
  65. #ifndef DP_NAMELEN
  66. #define DP_NAMELEN(x)    (x)->d_namlen
  67. #endif
  68.  
  69. #ifdef USG
  70. #include <sys/sysmacros.h>    /* major() and minor() defined here */
  71. #endif
  72.  
  73. /*
  74.  * V7 doesn't have a #define for this.
  75.  */
  76. #ifndef O_RDONLY
  77. #define    O_RDONLY    0
  78. #endif
  79.  
  80. /*
  81.  * Most people don't have a #define for this.
  82.  */
  83. #ifndef    O_BINARY
  84. #define    O_BINARY    0
  85. #endif
  86.  
  87. #include "tar.h"
  88. #include "port.h"
  89.  
  90. extern union record *head;        /* Points to current tape header */
  91. extern struct stat hstat;        /* Stat struct corresponding */
  92. extern int head_standard;        /* Tape header is in ANSI format */
  93.  
  94. /* JF */
  95. extern struct name *gnu_list_name;
  96.  
  97. /*
  98.  * If there are no symbolic links, there is no lstat().  Use stat().
  99.  */
  100. #ifndef S_IFLNK
  101. #define lstat stat
  102. #endif
  103.  
  104. extern char    *malloc();
  105. extern char    *strcpy();
  106. extern char    *strncpy();
  107. extern void    bzero();
  108. extern void    bcopy();
  109. extern int    errno;
  110.  
  111. extern void print_header();
  112.  
  113. union record *start_header();
  114. void finish_header();
  115. void finduname();
  116. void findgname();
  117. char *name_next();
  118. void to_oct();
  119. void dump_file();
  120.  
  121. static nolinks;            /* Gets set if we run out of RAM */
  122.  
  123. /*
  124.  * "Scratch" space to store the information about a sparse file before
  125.  * writing the info into the header or extended header
  126.  */
  127. /* struct sp_array     *sparsearray;*/
  128.  
  129. /* number of elts storable in the sparsearray */
  130. /*int     sparse_array_size = 10;*/
  131.  
  132. void
  133. create_archive()
  134. {
  135.     register char    *p;
  136.     char *name_from_list();
  137.  
  138.     open_archive(0);        /* Open for writing */
  139.  
  140.     if(f_gnudump) {
  141.         char buf[MAXNAMLEN],*q,*bufp;
  142.  
  143.         collect_and_sort_names();
  144.  
  145.         while(p=name_from_list())
  146.             dump_file(p,-1);
  147.         /* if(!f_dironly) { */
  148.             blank_name_list();
  149.             while(p=name_from_list()) {
  150.                 strcpy(buf,p);
  151.                 if(p[strlen(p)-1]!='/')
  152.                     strcat(buf,"/");
  153.                 bufp=buf+strlen(buf);
  154.                 for(q=gnu_list_name->dir_contents;*q;q+=strlen(q)+1) {
  155.                     if(*q=='Y') {
  156.                         strcpy(bufp,q+1);
  157.                         dump_file(buf,-1);
  158.                     }
  159.                 }
  160.             }
  161.         /* } */
  162.     
  163.     } else {
  164.         while (p = name_next(1)) {
  165.             dump_file(p, -1);
  166.         }
  167.     }
  168.  
  169.     write_eot();
  170.     close_archive();
  171.     name_close();
  172. }
  173.  
  174. /*
  175.  * Dump a single file.  If it's a directory, recurse.
  176.  * Result is 1 for success, 0 for failure.
  177.  * Sets global "hstat" to stat() output for this file.
  178.  */
  179. void
  180. dump_file (p, curdev)
  181.     char    *p;            /* File name to dump */
  182.     int    curdev;            /* Device our parent dir was on */
  183. {
  184.     union record    *header;
  185.     char type;
  186.     extern char *save_name;        /* JF for multi-volume support */
  187.     extern long save_totsize;
  188.     extern long save_sizeleft;
  189.     union record    *exhdr;
  190.     char save_linkflag;
  191.     extern time_t new_time;
  192.     int sparse_ind = 0;
  193.  
  194.  
  195.     if(f_confirm && !confirm("add",p))
  196.         return;
  197.  
  198.     /*
  199.      * Use stat if following (rather than dumping) 4.2BSD's
  200.      * symbolic links.  Otherwise, use lstat (which, on non-4.2
  201.      * systems, is #define'd to stat anyway.
  202.      */
  203.     if (0 != f_follow_links? stat(p, &hstat): lstat(p, &hstat))
  204.     {
  205. badperror:
  206.         msg_perror("can't add file %s",p);
  207. badfile:
  208.         errors++;
  209.         return;
  210.     }
  211.  
  212.     /* See if we only want new files, and check if this one is too old to
  213.        put in the archive. */
  214.     if(   f_new_files
  215.         && new_time>hstat.st_mtime
  216.         && (hstat.st_mode&S_IFMT)!=S_IFDIR
  217.         && (f_new_files>1 || new_time>hstat.st_ctime)) {
  218.         if(curdev<0) {
  219.             msg("%s: is unchanged; not dumped",p);
  220.         }
  221.         return;
  222.     }
  223.  
  224.     /*
  225.      * See if we are crossing from one file system to another,
  226.      * and avoid doing so if the user only wants to dump one file system.
  227.      */
  228.     if (f_local_filesys && curdev >= 0 && curdev != hstat.st_dev) {
  229.         msg("%s: is on a different filesystem; not dumped",p);
  230.         return;
  231.     }
  232.  
  233.     /*
  234.      * Check for multiple links.
  235.      *
  236.      * We maintain a list of all such files that we've written so
  237.      * far.  Any time we see another, we check the list and
  238.      * avoid dumping the data again if we've done it once already.
  239.      */
  240.     if (hstat.st_nlink > 1) switch (hstat.st_mode & S_IFMT) {
  241.         register struct link    *lp;
  242.  
  243.     case S_IFREG:            /* Regular file */
  244. #ifdef S_IFCTG
  245.     case S_IFCTG:            /* Contigous file */
  246. #endif
  247. #ifdef S_IFCHR
  248.     case S_IFCHR:            /* Character special file */
  249. #endif
  250.  
  251. #ifdef S_IFBLK
  252.     case S_IFBLK:            /* Block     special file */
  253. #endif
  254.  
  255. #ifdef S_IFIFO
  256.     case S_IFIFO:            /* Fifo      special file */
  257. #endif
  258.  
  259.         /* First quick and dirty.  Hashing, etc later FIXME */
  260.         for (lp = linklist; lp; lp = lp->next) {
  261.             if (lp->ino == hstat.st_ino &&
  262.                 lp->dev == hstat.st_dev) {
  263.                 char *link_name = lp->name;
  264.  
  265.                 /* We found a link. */
  266.                 hstat.st_size = 0;
  267.                 header = start_header(p, &hstat);
  268.                 if (header == NULL) goto badfile;
  269.                 while(!f_absolute_paths && *link_name == '/') {
  270.                     static int link_warn = 0;
  271.  
  272.                     if (!link_warn) {
  273.                         msg("Removing leading / from absolute links");
  274.                         link_warn++;
  275.                     }
  276.                     link_name++;
  277.                 }
  278.                   strcpy(header->header.linkname,
  279.                     link_name);
  280.                 header->header.linkflag = LF_LINK;
  281.                 finish_header(header);
  282.         /* FIXME: Maybe remove from list after all links found? */
  283.                 return;        /* We dumped it */
  284.             }
  285.         }
  286.  
  287.         /* Not found.  Add it to the list of possible links. */
  288.         lp = (struct link *) malloc( (unsigned)
  289.             (strlen(p) + sizeof(struct link) - NAMSIZ));
  290.         if (!lp) {
  291.             if (!nolinks) {
  292.                 fprintf(stderr,
  293.     "tar: no memory for links, they will be dumped as separate files\n");
  294.                 nolinks++;
  295.             }
  296.         }
  297.         lp->ino = hstat.st_ino;
  298.         lp->dev = hstat.st_dev;
  299.         strcpy(lp->name, p);
  300.         lp->next = linklist;
  301.         linklist = lp;
  302.     }
  303.  
  304.     /*
  305.      * This is not a link to a previously dumped file, so dump it.
  306.      */
  307.     switch (hstat.st_mode & S_IFMT) {
  308.  
  309.     case S_IFREG:            /* Regular file */
  310. #ifdef S_IFCTG
  311.     case S_IFCTG:            /* Contiguous file */
  312. #endif
  313.     {
  314.         int    f;        /* File descriptor */
  315.         long    bufsize, count;
  316.         long    sizeleft;
  317.         register union record     *start;
  318.         int     header_moved;
  319.         char    isextended = 0;
  320.         int     upperbound;
  321.         int    end_nulls = 0;
  322.         
  323.         header_moved = 0;
  324.  
  325. #ifdef BSD42
  326.         if (f_sparse_files) {
  327.         /*
  328.           * JK - This is the test for sparseness: whether the
  329.          * "size" of the file matches the number of blocks
  330.          * allocated for it.  If there is a smaller number
  331.          * of blocks that would be necessary to accommodate
  332.          * a file of this size, we have a sparse file, i.e.,
  333.          * at least one of those records in the file is just
  334.          * a useless hole.
  335.          */
  336.             if (hstat.st_size - (hstat.st_blocks * RECORDSIZE) > RECORDSIZE) {
  337.                 int    filesize = hstat.st_size;
  338.                 register int i;
  339.                 
  340.                 printf("File is sparse: %s\n", p);
  341.                 header = start_header(p, &hstat);
  342.                 if (header == NULL)
  343.                     goto badfile;
  344.                 header->header.linkflag = LF_SPARSE;
  345.                 header_moved++;
  346.                 
  347.             /*
  348.              * Call the routine that figures out the
  349.              * layout of the sparse file in question.
  350.              * UPPERBOUND is the index of the last
  351.              * element of the "sparsearray," i.e.,
  352.              * the number of elements it needed to
  353.              * describe the file.
  354.              */
  355.                  
  356.                 upperbound = deal_with_sparse(p, header);
  357.                          
  358.             /* 
  359.              * See if we'll need an extended header
  360.              * later
  361.              */
  362.                 if (upperbound > SPARSE_IN_HDR-1)
  363.                      header->header.isextended++;
  364.             /*
  365.              * We store the "real" file size so
  366.              * we can show that in case someone wants
  367.              * to list the archive, i.e., tar tvf <file>.
  368.              * It might be kind of disconcerting if the
  369.              * shrunken file size was the one that showed
  370.              * up.
  371.              */
  372.                  to_oct((long) hstat.st_size, 1+12, 
  373.                          header->header.realsize);
  374.                     
  375.             /*
  376.              * This will be the new "size" of the
  377.              * file, i.e., the size of the file
  378.              * minus the records of holes that we're
  379.              * skipping over. 
  380.              */
  381.                  
  382.                 find_new_file_size(&filesize, upperbound);
  383.                 printf("File %s is now size %d\n", 
  384.                             p, filesize);
  385.                 hstat.st_size = filesize;
  386.                 to_oct((long) filesize, 1+12,
  387.                          header->header.size);
  388. /*                to_oct((long) end_nulls, 1+12, 
  389.                         header->header.ending_blanks);*/
  390.                         
  391.                 for (i = 0; i < SPARSE_IN_HDR; i++) {
  392.                     if (!sparsearray[i].numbytes)
  393.                         break;
  394.                     to_oct(sparsearray[i].offset, 1+12,
  395.                         header->header.sp[i].offset);
  396.                     to_oct(sparsearray[i].numbytes, 1+12,
  397.                         header->header.sp[i].numbytes);
  398.                 }
  399.                     
  400.             }
  401.         }
  402. #endif
  403.         
  404.         sizeleft = hstat.st_size;
  405.         /* Don't bother opening empty, world readable files. */
  406.         if (sizeleft > 0 || 0444 != (0444 & hstat.st_mode)) {
  407.             f = open(p, O_RDONLY|O_BINARY);
  408.             if (f < 0) goto badperror;
  409.         } else {
  410.             f = -1;
  411.         }
  412.         
  413.         /* If the file is sparse, we've already taken care of this */
  414.         if (!header_moved) {
  415.             header = start_header(p, &hstat);
  416.             if (header == NULL) {
  417.                 if(f>=0)
  418.                     (void)close(f);
  419.                 goto badfile;
  420.             }
  421.         }
  422. #ifdef S_IFCTG
  423.         /* Mark contiguous files, if we support them */
  424.         if (f_standard && (hstat.st_mode & S_IFMT) == S_IFCTG) {
  425.             header->header.linkflag = LF_CONTIG;
  426.         }
  427. #endif
  428.         isextended = header->header.isextended;
  429.         save_linkflag = header->header.linkflag;
  430.         finish_header(header);
  431.         if (isextended) {
  432.             int     sum = 0;
  433.             register int i;
  434. /*            register union record *exhdr;*/
  435.             int     arraybound = SPARSE_EXT_HDR;
  436.             static int index_offset = SPARSE_IN_HDR;
  437.             
  438.     extend:        exhdr = findrec();
  439.             
  440.             if (exhdr == NULL) goto badfile;
  441.             bzero(exhdr->charptr, RECORDSIZE);
  442.             for (i = 0; i < SPARSE_EXT_HDR; i++) {
  443.                 if (i+index_offset > upperbound)
  444.                     break;
  445.                 to_oct((long) sparsearray[i+index_offset].numbytes,
  446.                      1+12,
  447.                     exhdr->ext_hdr.sp[i].numbytes);
  448.                 to_oct((long) sparsearray[i+index_offset].offset,
  449.                      1+12,
  450.                     exhdr->ext_hdr.sp[i].offset);
  451.             }
  452.             userec(exhdr);
  453. /*            sum += i;
  454.             if (sum < upperbound)
  455.                 goto extend;*/
  456.             if (index_offset+i < upperbound) {
  457.                 index_offset += i;
  458.                 exhdr->ext_hdr.isextended++;
  459.                 goto extend;
  460.             }
  461.                 
  462.         }
  463.         if (save_linkflag == LF_SPARSE) {
  464.             if (finish_sparse_file(f, &sizeleft, hstat.st_size, p))
  465.                 goto padit;
  466.         }
  467.         else
  468.           while (sizeleft > 0) {
  469.             
  470.             if(f_multivol) {   
  471.                 save_name = p;
  472.                 save_sizeleft = sizeleft;
  473.                 save_totsize = hstat.st_size;
  474.             }
  475.             start = findrec();
  476.  
  477.             bufsize = endofrecs()->charptr - start->charptr;
  478.                 
  479.             if (sizeleft < bufsize) {
  480.                 /* Last read -- zero out area beyond */
  481.                 bufsize = (int)sizeleft;
  482.                 count = bufsize % RECORDSIZE;
  483.                 if (count) 
  484.                     bzero(start->charptr + sizeleft,
  485.                         (int)(RECORDSIZE - count));
  486.             }
  487.             count = read(f, start->charptr, bufsize);
  488.             if (count < 0) {
  489.                 msg_perror("read error at byte %ld, reading\
  490.  %d bytes, in file %s",  hstat.st_size - sizeleft, bufsize,p);
  491.                 goto padit;
  492.             }
  493.             sizeleft -= count;
  494.  
  495.             /* This is nonportable (the type of userec's arg). */
  496.             userec(start+(count-1)/RECORDSIZE);
  497.  
  498.             if (count == bufsize) continue;
  499.             msg( "file %s shrunk by %d bytes, padding with zeros.\n", p, sizeleft);
  500.             goto padit;        /* Short read */
  501.         }
  502.  
  503.         if(f_multivol)
  504.             save_name = 0;
  505.  
  506.         if (f >= 0)
  507.             (void)close(f);
  508.  
  509.         break;
  510.  
  511.         /*
  512.          * File shrunk or gave error, pad out tape to match
  513.          * the size we specified in the header.
  514.          */
  515.     padit:
  516.         while(sizeleft>0) {
  517.             save_sizeleft=sizeleft;
  518.             start=findrec();
  519.             bzero(start->charptr,RECORDSIZE);
  520.             userec(start);
  521.             sizeleft-=RECORDSIZE;
  522.         }
  523.         if(f_multivol)
  524.             save_name=0;
  525.         if(f>=0)
  526.             (void)close(f);
  527.         break;
  528. /*        abort(); */
  529.     }
  530.  
  531. #ifdef S_IFLNK
  532.     case S_IFLNK:            /* Symbolic link */
  533.     {
  534.         int size;
  535.  
  536.         hstat.st_size = 0;        /* Force 0 size on symlink */
  537.         header = start_header(p, &hstat);
  538.         if (header == NULL) goto badfile;
  539.         size = readlink(p, header->header.linkname, NAMSIZ);
  540.         if (size < 0) goto badperror;
  541.         if (size == NAMSIZ) {
  542.             msg("symbolic link %s too long\n",p);
  543.             break;
  544.         }
  545.         header->header.linkname[size] = '\0';
  546.         header->header.linkflag = LF_SYMLINK;
  547.         finish_header(header);        /* Nothing more to do to it */
  548.     }
  549.         break;
  550. #endif
  551.  
  552.     case S_IFDIR:            /* Directory */
  553.     {
  554.         register DIR *dirp;
  555.         register struct direct *d;
  556.         char namebuf[NAMSIZ+2];
  557.         register int len;
  558.         int our_device = hstat.st_dev;
  559.  
  560.         /* Build new prototype name */
  561.         strncpy(namebuf, p, sizeof (namebuf));
  562.         len = strlen(namebuf);
  563.         while (len >= 1 && '/' == namebuf[len-1]) 
  564.             len--;            /* Delete trailing slashes */
  565.         namebuf[len++] = '/';        /* Now add exactly one back */
  566.         namebuf[len] = '\0';        /* Make sure null-terminated */
  567.  
  568.         /*
  569.          * Output directory header record with permissions
  570.          * FIXME, do this AFTER files, to avoid R/O dir problems?
  571.          * If old archive format, don't write record at all.
  572.          */
  573.         if (!f_oldarch) {
  574.             hstat.st_size = 0;    /* Force 0 size on dir */
  575.             /*
  576.              * If people could really read standard archives,
  577.              * this should be:        (FIXME)
  578.             header = start_header(f_standard? p: namebuf, &hstat);
  579.              * but since they'd interpret LF_DIR records as
  580.              * regular files, we'd better put the / on the name.
  581.              */
  582.             header = start_header(namebuf, &hstat);
  583.             if (header == NULL)
  584.                 goto badfile;    /* eg name too long */
  585.  
  586.             if (f_gnudump)
  587.                 header->header.linkflag = LF_DUMPDIR;
  588.             else if (f_standard)
  589.                 header->header.linkflag = LF_DIR;
  590.  
  591.             /* If we're gnudumping, we aren't done yet so don't close it. */
  592.             if(!f_gnudump)
  593.                 finish_header(header);    /* Done with directory header */
  594.         }
  595.  
  596.         /* Hack to remove "./" from the front of all the file names */
  597.         if (len == 2 && namebuf[0] == '.' && namebuf[1]=='/') {
  598.             len = 0;
  599.         }
  600.  
  601.         if(f_gnudump) {
  602.             int sizeleft;
  603.             int totsize;
  604.             int bufsize;
  605.             union record *start;
  606.             int count;
  607.             char *buf,*p_buf;
  608.  
  609.             buf=gnu_list_name->dir_contents; /* FOO */
  610.             totsize=0;
  611.             for(p_buf=buf;*p_buf;) {
  612.                 int tmp;
  613.  
  614.                 tmp=strlen(p_buf)+1;
  615.                 totsize+=tmp;
  616.                 p_buf+=tmp;
  617.             }
  618.             totsize++;
  619.             to_oct((long)totsize,1+12,header->header.size);
  620.             finish_header(header);
  621.             p_buf=buf;
  622.             sizeleft=totsize;
  623.             while(sizeleft>0) {
  624.                 if(f_multivol) {
  625.                     save_name=p;
  626.                     save_sizeleft=sizeleft;
  627.                     save_totsize=totsize;
  628.                 }
  629.                 start=findrec();
  630.                 bufsize=endofrecs()->charptr - start->charptr;
  631.                 if(sizeleft<bufsize) {
  632.                     bufsize=sizeleft;
  633.                     count=bufsize%RECORDSIZE;
  634.                     if(count)
  635.                         bzero(start->charptr+sizeleft,RECORDSIZE-count);
  636.                 }
  637.                 bcopy(p_buf,start->charptr,bufsize);
  638.                 sizeleft-=bufsize;
  639.                 p_buf+=bufsize;
  640.                 userec(start+(bufsize-1)/RECORDSIZE);
  641.             }
  642.             if(f_multivol)
  643.                 save_name = 0;
  644.             break;
  645.         }
  646.  
  647.         /* Now output all the files in the directory */
  648.         /* if (f_dironly)
  649.             break;        /* Unless the cmdline said not to */
  650.  
  651.         
  652.         errno = 0;
  653.         dirp = opendir(p);
  654.         if (!dirp) {
  655.             if (errno) {
  656.                 msg_perror ("can't open directory %s",p);
  657.             } else {
  658.                 msg("error opening directory %s",
  659.                     p);
  660.             }
  661.             break;
  662.         }
  663.  
  664.         /* Should speed this up by cd-ing into the dir, FIXME */
  665.         while (NULL != (d=readdir(dirp))) {
  666.             /* Skip . and .. */
  667.             if(is_dot_or_dotdot(d->d_name))
  668.                 continue;
  669.  
  670.             if (DP_NAMELEN(d) + len >= NAMSIZ) {
  671.                 msg("file name %s%s too long\n", 
  672.                     namebuf, d->d_name);
  673.                 continue;
  674.             }
  675.             strcpy(namebuf+len, d->d_name);
  676.             if(f_exclude && check_exclude(namebuf))
  677.                 continue;
  678.             dump_file(namebuf, our_device);
  679.         }
  680.  
  681.         closedir(dirp);
  682.     }
  683.         break;
  684.  
  685. #ifdef S_IFCHR
  686.     case S_IFCHR:            /* Character special file */
  687.         type = LF_CHR;
  688.         goto easy;
  689. #endif
  690.  
  691. #ifdef S_IFBLK
  692.     case S_IFBLK:            /* Block     special file */
  693.         type = LF_BLK;
  694.         goto easy;
  695. #endif
  696.  
  697. #ifdef S_IFIFO
  698.     case S_IFIFO:            /* Fifo      special file */
  699.         
  700.         type = LF_FIFO;
  701. #endif
  702.  
  703.     easy:
  704.         if (!f_standard) goto unknown;
  705.  
  706.         hstat.st_size = 0;        /* Force 0 size */
  707.         header = start_header(p, &hstat);
  708.         if (header == NULL) goto badfile;    /* eg name too long */
  709.  
  710.         header->header.linkflag = type;
  711.         if (type != LF_FIFO) {
  712.             to_oct((long) major(hstat.st_rdev), 8,
  713.                 header->header.devmajor);
  714.             to_oct((long) minor(hstat.st_rdev), 8,
  715.                 header->header.devminor);
  716.         }
  717.  
  718.         finish_header(header);
  719.         break;
  720.  
  721.     default:
  722.     unknown:
  723.         msg("%s: Unknown file type; file ignored.\n", p);
  724.         break;
  725.     }
  726. }
  727.  
  728. int
  729. finish_sparse_file(fd, sizeleft, fullsize, name)
  730.     int    fd;
  731.     long     *sizeleft,
  732.         fullsize;
  733.     char    *name;
  734. {
  735.     union record    *start;
  736.     char        tempbuf[RECORDSIZE];
  737.     int        bufsize,
  738.             sparse_ind = 0,
  739.             count;
  740.     long        pos;
  741.  
  742.  
  743.  
  744.     while (*sizeleft > 0) {
  745.         start = findrec();
  746.         bzero(start->charptr, RECORDSIZE);
  747.         bufsize = sparsearray[sparse_ind].numbytes;
  748.         if (!bufsize) {  /* we blew it, maybe */
  749.                 fprintf(stderr, "Wrote %ld of %ld bytes to file %s\n",
  750.                        fullsize - *sizeleft, fullsize, name);
  751.             break;
  752.              }
  753.         pos = lseek(fd, sparsearray[sparse_ind++].offset, 0);
  754.         /* 
  755.          * If the number of bytes to be written here exceeds
  756.          * the size of the temporary buffer, do it in steps.
  757.          */
  758.         while (bufsize > RECORDSIZE) {
  759. /*            if (amt_read) {
  760.                 count = read(fd, start->charptr+amt_read, RECORDSIZE-amt_read);
  761.                 bufsize -= RECORDSIZE - amt_read;
  762.                 amt_read = 0;
  763.                 userec(start);
  764.                 start = findrec();
  765.                 bzero(start->charptr, RECORDSIZE);
  766.             }*/
  767.             /* store the data */
  768.             count = read(fd, start->charptr, RECORDSIZE);
  769.             if (count < 0)     {
  770.                 msg_perror("read error at byte %ld, reading %d bytes, in file %s", 
  771.                         fullsize - *sizeleft, bufsize, name);
  772.                 return 1;
  773.             }            
  774.             bufsize -= count;
  775.             *sizeleft -= count;
  776.             userec(start);
  777.             start = findrec();
  778.             bzero(start->charptr, RECORDSIZE);
  779.         }
  780.  
  781.  
  782.         clear_buffer(tempbuf);
  783.         count = read(fd, tempbuf, bufsize);
  784.         bcopy(tempbuf, start->charptr, RECORDSIZE);
  785.         if (count < 0)     {
  786.             msg_perror("read error at byte %ld, reading %d bytes, in file %s", 
  787.                     fullsize - *sizeleft, bufsize, name);
  788.             return 1;
  789.         }
  790. /*        if (amt_read >= RECORDSIZE) {
  791.             amt_read = 0;
  792.             userec(start+(count-1)/RECORDSIZE);
  793.             if (count != bufsize) {
  794.                 msg("file %s shrunk by %d bytes, padding with zeros.\n", name, sizeleft);
  795.                 return 1;
  796.             }
  797.             start = findrec();
  798.         } else 
  799.             amt_read += bufsize;*/
  800.         *sizeleft -= count;
  801.         userec(start);
  802.  
  803.     }
  804. /*    userec(start+(count-1)/RECORDSIZE);*/
  805.     return 0;
  806.  
  807. }
  808.  
  809. init_sparsearray()
  810. {
  811.     register int i;
  812.  
  813.     for (i = 0; i < sp_array_size; i++) {
  814.         sparsearray[i].offset = 0;
  815.         sparsearray[i].numbytes = 0;
  816.     }
  817. }
  818.  
  819.  
  820.  
  821. /*
  822.  * Okay, we've got a sparse file on our hands -- now, what we need to do is
  823.  * make a pass through the file and carefully note where any data is, i.e.,
  824.  * we want to find how far into the file each instance of data is, and how
  825.  * many bytes are there.  We store this information in the sparsearray,
  826.  * which will later be translated into header information.  For now, we use
  827.  * the sparsearray as convenient storage.
  828.  *
  829.  * As a side note, this routine is a mess.  If I could have found a cleaner
  830.  * way to do it, I would have.  If anyone wants to find a nicer way to do
  831.  * this, feel free.
  832.  */
  833. int
  834. deal_with_sparse(name, header, nulls_at_end)
  835.     char        *name;
  836.     union record     *header;
  837.     
  838. {
  839.     long    numbytes = 0;
  840.     long    offset = 0;
  841.     long    save_offset;
  842.     int    fd;
  843.     int    start,
  844.         end;
  845.     int    end_nulls = 0;
  846.     int    current_size = hstat.st_size;
  847.     int    sparse_ind = 0,
  848.         cc;
  849.     char    buf[RECORDSIZE];
  850.     int    read_last_data = 0; /* did we just read the last record? */
  851.     int     amidst_data = 0;
  852.     
  853.     header->header.isextended = 0;
  854.     /* 
  855.      * Can't open the file -- this problem will be caught later on,
  856.      * so just return.
  857.      */
  858.     if ((fd = open(name, O_RDONLY)) < 0)
  859.         return;
  860.         
  861.     sp_array_size = 10;
  862.     /* 
  863.      * Make room for our scratch space -- initially is 10 elts long
  864.      */
  865.     sparsearray = (struct sp_array *) malloc(sp_array_size * sizeof(struct sp_array));
  866.  
  867.     init_sparsearray();
  868.     clear_buffer(buf);
  869.  
  870.     while ((cc = read(fd, buf, sizeof buf)) != 0) {
  871.             
  872.         if (sparse_ind > sp_array_size-1) {
  873.         
  874.         /*
  875.          * realloc the scratch area, since we've run out of room --
  876.          */
  877.             sparsearray = (struct sp_array *) 
  878.                     realloc(sparsearray,
  879.                          2 * sp_array_size * (sizeof(struct sp_array)));
  880.             sp_array_size *= 2;
  881.         }
  882.         if (cc == sizeof buf) {
  883.             if (zero_record(buf)) {
  884.                 if (amidst_data) {
  885.                     sparsearray[sparse_ind++].numbytes
  886.                         = numbytes;
  887.                     amidst_data = 0;
  888.                     numbytes = 0;
  889.                 }
  890.                 offset += cc;
  891.             } else {  /* !zero_record(buf) */
  892.                 if (!amidst_data) {
  893.                         amidst_data = 1;
  894.                     where_is_data(&start, &end, buf);
  895.                     numbytes += end - start;
  896.                     offset += start;
  897.                     sparsearray[sparse_ind].offset = offset;
  898.                 } else
  899.                     numbytes += cc;
  900.                 offset += cc;
  901.             }
  902.         } else if (cc < sizeof buf) {
  903.             if (!zero_record(buf)) {
  904.                 if (!amidst_data) {
  905.                     amidst_data = 1;
  906.                     where_is_data(&start, &end, buf);
  907.                     /* In case there are nulls at the 
  908.                        end that we need to remember */
  909.                     if (end < cc)
  910.                         end = cc;
  911.                     numbytes += start - end;
  912.                     offset += start;
  913. /*                    end_nulls = RECORDSIZE - end;*/
  914.                 } else {
  915.                     numbytes += cc;
  916. /*                    end_nulls = RECORDSIZE - end;*/
  917.                 }
  918.                 sparsearray[sparse_ind].numbytes = numbytes;
  919.             } /* else
  920.                 end_nulls = cc;*/
  921.         }
  922.         clear_buffer(buf);
  923.     }
  924.     if (numbytes)
  925.             sparsearray[sparse_ind].numbytes = numbytes;
  926.     close(fd);
  927. /*    printf("%d\n", end_nulls);
  928.     *nulls_at_end = end_nulls;*/
  929.  
  930.     return sparse_ind;
  931. }
  932.  
  933. /* 
  934.  * Just zeroes out the buffer so we don't confuse ourselves with leftover
  935.  * data.
  936.  */
  937. clear_buffer(buf)
  938.     char    *buf;
  939. {
  940.     register int     i;
  941.  
  942.     for (i = 0; i < RECORDSIZE; i++)
  943.         buf[i] = '\0';
  944. }
  945.  
  946. /* 
  947.  * JK - 
  948.  * This routine takes a character array, and tells where within that array
  949.  * the data can be found.  It skips over any zeros, and sets the first
  950.  * non-zero point in the array to be the "start", and continues until it
  951.  * finds non-data again, which is marked as the "end."  This routine is 
  952.  * mainly for 1) seeing how far into a file we must lseek to data, given
  953.  * that we have a sparse file, and 2) determining the "real size" of the
  954.  * file, i.e., the number of bytes in the sparse file that are data, as
  955.  * opposed to the zeros we are trying to skip.
  956.  */
  957. where_is_data(from, to, buffer)
  958.     int    *from,
  959.         *to;
  960.     char    *buffer;
  961. {
  962.     register int    i = 0;
  963.     register int    save_to = *to;
  964.     int    amidst_data = 0;
  965.  
  966.     
  967.     while (!buffer[i])
  968.         i++;
  969.     *from = i;
  970.  
  971.     if (*from < 16)    /* don't bother */
  972.         *from = 0;
  973.     /* keep going to make sure there isn't more real
  974.        data in this record */
  975.     while (i < RECORDSIZE) {
  976.         if (!buffer[i]) {
  977.             if (amidst_data) {
  978.                 save_to = i;
  979.                 amidst_data = 0;
  980.             }
  981.             i++;
  982.         }
  983.         else if (buffer[i]) {
  984.             if (!amidst_data)
  985.                 amidst_data = 1;
  986.             i++;
  987.         }
  988.     }
  989.     if (i == RECORDSIZE)
  990.         *to = i;
  991.     else
  992.         *to = save_to;
  993.         
  994. }
  995.  
  996. /*
  997.  * Takes a recordful of data and basically cruises through it to see if
  998.  * it's made *entirely* of zeros, returning a 0 the instant it finds
  999.  * something that is a non-zero, i.e., useful data.
  1000.  */
  1001. zero_record(buffer)
  1002.     char    *buffer;
  1003. {
  1004.     register int    i;
  1005.  
  1006.     for (i = 0; i < RECORDSIZE; i++)
  1007.         if (buffer[i] != '\000')
  1008.             return 0;
  1009.     return 1;
  1010. }
  1011.  
  1012. find_new_file_size(filesize, highest_index)
  1013.     int    *filesize;
  1014.     int    highest_index;
  1015. {
  1016.     register int     i;
  1017.  
  1018.     *filesize = 0;
  1019.     for (i = 0; sparsearray[i].numbytes && i <= highest_index; i++)
  1020.         *filesize += sparsearray[i].numbytes;
  1021. }
  1022.     
  1023. /*
  1024.  * Make a header block for the file  name  whose stat info is  st .
  1025.  * Return header pointer for success, NULL if the name is too long.
  1026.  */
  1027. union record *
  1028. start_header(name, st)
  1029.     char    *name;
  1030.     register struct stat *st;
  1031. {
  1032.     register union record *header;
  1033.  
  1034.     header = (union record *) findrec();
  1035.     bzero(header->charptr, sizeof(*header)); /* XXX speed up */
  1036.  
  1037.     /*
  1038.      * Check the file name and put it in the record.
  1039.      */
  1040. #ifdef MSDOS
  1041.     if(name[1]==':') {
  1042.         static int warned_once = 0;
  1043.         name+=2;
  1044.         if(!warned_once++) {
  1045.             msg("Removing drive spec from names in the archive");
  1046.         }
  1047.     }
  1048. #endif
  1049.     while (!f_absolute_paths && '/' == *name) {
  1050.         static int warned_once = 0;
  1051.  
  1052.         name++;                /* Force relative path */
  1053.         if (!warned_once++) {
  1054.             msg("Removing leading / from absolute path names in the archive.");
  1055.         }
  1056.     }
  1057.     strcpy(header->header.name, name);
  1058.     if (header->header.name[NAMSIZ-1]) {
  1059.         msg("%s: name too long\n", name);
  1060.         return NULL;
  1061.     }
  1062.  
  1063.     to_oct((long) (st->st_mode & ~S_IFMT),
  1064.                     8,  header->header.mode);
  1065.     to_oct((long) st->st_uid,    8,  header->header.uid);
  1066.     to_oct((long) st->st_gid,    8,  header->header.gid);
  1067.     to_oct((long) st->st_size,    1+12, header->header.size);
  1068.     to_oct((long) st->st_mtime,    1+12, header->header.mtime);
  1069.     /* header->header.linkflag is left as null */
  1070.     if(f_gnudump) {
  1071.         to_oct((long) st->st_atime, 1+12, header->header.atime);
  1072.         to_oct((long) st->st_ctime, 1+12, header->header.ctime);
  1073.     }
  1074.  
  1075. #ifndef NONAMES
  1076.     /* Fill in new Unix Standard fields if desired. */
  1077.     if (f_standard) {
  1078.         header->header.linkflag = LF_NORMAL;    /* New default */
  1079.         strcpy(header->header.magic, TMAGIC);    /* Mark as Unix Std */
  1080.         finduname(header->header.uname, st->st_uid);
  1081.         findgname(header->header.gname, st->st_gid);
  1082.     }
  1083. #endif
  1084.     return header;
  1085. }
  1086.  
  1087. /* 
  1088.  * Finish off a filled-in header block and write it out.
  1089.  * We also print the file name and/or full info if verbose is on.
  1090.  */
  1091. void
  1092. finish_header(header)
  1093.     register union record *header;
  1094. {
  1095.     register int    i, sum;
  1096.     register char    *p;
  1097.     void bcopy();
  1098.  
  1099.     bcopy(CHKBLANKS, header->header.chksum, sizeof(header->header.chksum));
  1100.  
  1101.     sum = 0;
  1102.     p = header->charptr;
  1103.     for (i = sizeof(*header); --i >= 0; ) {
  1104.         /*
  1105.          * We can't use unsigned char here because of old compilers,
  1106.          * e.g. V7.
  1107.          */
  1108.         sum += 0xFF & *p++;
  1109.     }
  1110.  
  1111.     /*
  1112.      * Fill in the checksum field.  It's formatted differently
  1113.      * from the other fields:  it has [6] digits, a null, then a
  1114.      * space -- rather than digits, a space, then a null.
  1115.      * We use to_oct then write the null in over to_oct's space.
  1116.      * The final space is already there, from checksumming, and
  1117.      * to_oct doesn't modify it.
  1118.      *
  1119.      * This is a fast way to do:
  1120.      * (void) sprintf(header->header.chksum, "%6o", sum);
  1121.      */
  1122.     to_oct((long) sum,    8,  header->header.chksum);
  1123.     header->header.chksum[6] = '\0';    /* Zap the space */
  1124.  
  1125.     userec(header);
  1126.  
  1127.     if (f_verbose) {
  1128.         /* These globals are parameters to print_header, sigh */
  1129.         head = header;
  1130.         /* hstat is already set up */
  1131.         head_standard = f_standard;
  1132.         print_header();
  1133.     }
  1134.  
  1135.     return;
  1136. }
  1137.  
  1138.  
  1139. /*
  1140.  * Quick and dirty octal conversion.
  1141.  * Converts long "value" into a "digs"-digit field at "where",
  1142.  * including a trailing space and room for a null.  "digs"==3 means
  1143.  * 1 digit, a space, and room for a null.
  1144.  *
  1145.  * We assume the trailing null is already there and don't fill it in.
  1146.  * This fact is used by start_header and finish_header, so don't change it!
  1147.  *
  1148.  * This should be equivalent to:
  1149.  *    (void) sprintf(where, "%*lo ", digs-2, value);
  1150.  * except that sprintf fills in the trailing null and we don't.
  1151.  */
  1152. void
  1153. to_oct(value, digs, where)
  1154.     register long    value;
  1155.     register int    digs;
  1156.     register char    *where;
  1157. {
  1158.     
  1159.     --digs;                /* Trailing null slot is left alone */
  1160.     where[--digs] = ' ';        /* Put in the space, though */
  1161.  
  1162.     /* Produce the digits -- at least one */
  1163.     do {
  1164.         where[--digs] = '0' + (char)(value & 7); /* one octal digit */
  1165.         value >>= 3;
  1166.     } while (digs > 0 && value != 0);
  1167.  
  1168.     /* Leading spaces, if necessary */
  1169.     while (digs > 0)
  1170.         where[--digs] = ' ';
  1171.  
  1172. }
  1173.  
  1174.  
  1175. /*
  1176.  * Write the EOT record(s).
  1177.  * We actually zero at least one record, through the end of the block.
  1178.  * Old tar writes garbage after two zeroed records -- and PDtar used to.
  1179.  */
  1180. write_eot()
  1181. {
  1182.     union record *p;
  1183.     int bufsize;
  1184.     void bzero();
  1185.  
  1186.     p = findrec();
  1187.     bufsize = endofrecs()->charptr - p->charptr;
  1188.     bzero(p->charptr, bufsize);
  1189.     userec(p);
  1190. }
  1191.